<?php


function image_one($gd_resource)
{
	// 去掉干扰线
	$canvas = img_line($gd_resource);

	// 切片
	$chunk_set = img_split($canvas);

	// 销毁图片资源
	imagedestroy($canvas);

	// 拼接成图
	$path = dirname(__DIR__).'/temp/black.png';
	img_draw_array($chunk_set, $path);

	return $path;
}



// 放大图片
function img_resize($im, $val = 3)  
{  
    $w = imagesx($im);
    $h = imagesy($im);
    $newwidth  = $w * $val;
    $newheight = $h * $val;

    if(function_exists("imagecopyresampled")) {
		$newim = imagecreatetruecolor($newwidth,$newheight);
		imagecopyresampled($newim,$im,0,0,0,0,$newwidth,$newheight,$w,$h);
    } else {
    	$newim = imagecreate($newwidth,$newheight);
		imagecopyresized($newim,$im,0,0,0,0,$newwidth,$newheight,$w,$h);
    }

	return $newim;    
}


// 二值图
function black($path)
{
	$gd_resource = imagecreatefrompng($path);
	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);

	$canvas= imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($canvas, 0, 0, 0);
	$white = imagecolorallocate($canvas, 255, 255, 255);

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	if (isBlack(getRGB($gd_resource, $i, $j))) {
		    	imagesetpixel($canvas, $i, $j, $black);
	    	} else {
		    	imagesetpixel($canvas, $i, $j, $white);
	    	}

    	}
    }
    
    return $canvas;
}


/**
 * 将字符图片切分成单个字符
 * @param  resource $gd_resource 图片资源
 * @param  integer  $filter      过滤掉小于10个点的块
 * @return yet/return resource
 */
function img_split($gd_resource, $filter = 30)
{
	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);

	// 遍历所有的点
	$chunk_set = array();

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	// 黑点计算块区域
	    	if (isBlack(getRGB($gd_resource, $i, $j))) {
	    		$chunk  = array();
		    	$offset = img_chunk($gd_resource, $chunk, $i, $j);
		    	if (count($chunk) >= $filter) {
			    	$chunk_set[] = [$chunk, $offset];
		    	}

		    	// 使用偏移量,不需要重新裁剪
		    	$i = $offset[2];
		    	$j = $offset[3];
	    	}

	    }
	}
	
	return $chunk_set;
}


/**
 * 查找资源块
 * @param  resource  $gd_resource 图片资源
 * @param  Array     $point_set   点集合
 * @param  integer   $x           位置x
 * @param  integer   $y           位置y
 * @param  Array     $point_set   与这个点相关的点
 * @return Array [minX,minY,maxX,maxY]
 */
function img_chunk(&$gd_resource, Array &$point_set = [], $x=1, $y=1, Array $relate = [])
{
	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);

	// 到边界了
	if ($x<0 || $y<0 || $x>($w-1) || $y>($h-1)) {
		return NULL;
	}

	// 已经统计过这个点了
	$key = "{$x}.{$y}";
	if (@$point_set[$key]) {
		return NULL;
	}

	// 白色跳出
	$rgb = getRGB($gd_resource, $x, $y);
	if (!isBlack($rgb)) {
		return NULL;
	}

	// 颜色相差太大跳出
	if (count($relate)) {
		$target = getRGB($gd_resource, $relate[0], $relate[1]);
		if (!isLike($rgb, $target)) {
			return NULL;
		}
	}

	// 保存当前
	$point = [$x, $y];
	$point_set[$key] = $point;


	$list_pos = Array();

	// 上
	$list_pos[] = img_chunk($gd_resource, $point_set, $x, $y-1, $point);

	// 上-右
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y-1, $point);
	
	// 右
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y, $point);

	// 右-下
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y+1, $point);

	// 下
	$list_pos[] = img_chunk($gd_resource, $point_set, $x, $y+1, $point);

	// 下-左
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y+1, $point);

	// 左
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y, $point);

	// 左-上
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y-1, $point);


	// 筛选最小的点与最大的点;
	$offset = deepin($list_pos, [$x, $y, $x, $y]);

	// 返回最小偏移点,和最大偏移点
	return $offset;
}


/**
 * 获取颜色值
 *
 * @param  [type] $gd_resource [description]
 * @param  [type] $i           [description]
 * @param  [type] $j           [description]
 * @return [type]              [description]
 */
function getRGB($gd_resource, $i, $j)
{
	$rgb = imagecolorat($gd_resource, $i, $j);
	$r = ($rgb >> 16) & 0xFF;
	$g = ($rgb >> 8) & 0xFF;
	$b = $rgb & 0xFF;
	return ['r'=>$r, 'g'=>$g, 'b'=>$b];
}


/**
 * 是否黑色,通过阀值取点
 * 
 * @param  [type]  $rgb [description]
 * @return boolean      [description]
 */
function isBlack($rgb)
{
	static $limit = ['r' => 180, 'g' => 150, 'b' => 256];
	return ($rgb['r'] < $limit['r'] 
        	&& $rgb['g'] < $limit['g'] 
        	&& $rgb['b'] < $limit['b']);
}


/**
 * 颜色相似的点
 * 
 * @param  Array   $rgb    [description]
 * @param  integer $scalar [description]
 * @return boolean         [description]
 */
function isLike(Array $rgb, Array $target,$scalar = 28)
{
	$ret = (abs($rgb['r'] - $target['r']) < $scalar 
		&& abs($rgb['g'] - $target['g']) < $scalar 
		&& abs($rgb['b'] - $target['b']) < $scalar);
	return $ret;
}


/**
 * 获取深度点
 * 
 * @param  Array   $list_pos 目标点
 * @param  Array   $current  当前区域
 * @return Array|null
 */
function deepin(Array $list_pos, Array $current)
{
	list($c_minX, $c_minY, $c_maxX, $c_maxY) = $current;

	foreach ($list_pos as $pos) {

		if (empty($pos)) continue;

		list($p_minX, $p_minY, $p_maxX, $p_maxY) = $pos;

		if ($p_minX < $c_minX) {
			$c_minX = $p_minX;
		}

		if ($p_minY < $c_minY) {
			$c_minY = $p_minY;
		}

		if ($p_maxX > $c_maxX) {
			$c_maxX = $p_maxX;
		}

		if ($p_maxY > $c_maxY) {
			$c_maxY = $p_maxY;
		}

	}

	return [$c_minX, $c_minY, $c_maxX, $c_maxY];
}



/**
 * 图片的点
 * @param  Array  $chunk   [description]
 * @return NULL            [description]
 */
function img_draw(Array $chunk, $name = '1.png')
{
	$list_point = $chunk[0];
	list($minX, $minY, $maxX, $maxY) = $chunk[1];
	
	$w = $maxX - $minX + 1;
	$h = $maxY - $minY + 1;
	$canvas= imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($canvas, 0, 0, 0);
	$white = imagecolorallocate($canvas, 255, 255, 255);

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {
	    	
	    	$pos_i = $i + $minX;
	    	$pos_j = $j + $minY;
	    	$key = "{$pos_i}.{$pos_j}";
	    	if (array_key_exists($key, $list_point)) {
		    	imagesetpixel($canvas, $i, $j, $black);
	    	} else {
		    	imagesetpixel($canvas, $i, $j, $white);
	    	}

    	}
    }

    imagepng($canvas, $name);
    imagedestroy($canvas);
}


function img_draw_array(Array $chunk_set, $name = '1.png')
{
	// 计算图片宽度
	$width  = 0;
	$height = 0;
	foreach ($chunk_set as $chunk) {
		$list_point = $chunk[0];
		list($minX, $minY, $maxX, $maxY) = $chunk[1];
		$width += ($maxX - $minX) + 2;
		$temp   = $maxY - $minY;
		if ($temp > $height) {
			$height = $temp;
		}
	}

	$canvas= imagecreatetruecolor($width, $height);
	$white = imagecolorallocate($canvas, 255, 255, 255);
	$black = imagecolorallocate($canvas, 0, 0, 0);

	// 绘图开始的偏移量
	$draw_char = function($chunk, $offset) use ($canvas, $height, $black, $white){

		$list_point = $chunk[0];
		list($minX, $minY, $maxX, $maxY) = $chunk[1];
		
		$w = $maxX - $minX;
		$h = $height;

		// 绘上字
		for ($i=0; $i<$w; $i++) {

		    for ($j=0; $j<$h; $j++) {

		    	$pos_i = $i + $minX;
		    	$pos_j = $j + $minY;
		    	$key = "{$pos_i}.{$pos_j}";

		    	$x = $i + $offset;
		    	if (array_key_exists($key, $list_point)) {
			    	imagesetpixel($canvas, $x, $j, $black);
		    	} else {
			    	imagesetpixel($canvas, $x, $j, $white);
		    	}

		    }
		}

		// 绘上空隙中的白背景
		for ($i=$x+1; $i <= ($x+2); $i++) {

			for ($j=0; $j < $h; $j++) {

		    	imagesetpixel($canvas, $i, $j, $white);
			}
		}

	    $offset += $w;

		return $offset;
	};


	$offset = 0;
	foreach ($chunk_set as $chunk) {
		$offset = $draw_char($chunk, $offset);
		$offset += 2;
	}

	imagepng($canvas, $name);
}


/**
 * 去掉干扰线
 */
function img_line($gd_resource)
{
	$w 	   = imagesx($gd_resource);
	$h 	   = imagesy($gd_resource);
	$canvas= imagecreatetruecolor($w, $h);
	$white = imagecolorallocate($canvas, 255, 255, 255);

	// 纵向过滤点
	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	$rgb = getRGB($gd_resource, $i, $j);

	    	// 白色直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($canvas, $i, $j, $white);
	            continue;
	        }

	        // 记录数值 >=2 的值
	        $count = 0;
	        $mark  = [];
	        while (isBlack($rgb) && ++$count && $j < $h) {
	        	$mark[] = [$i, $j, $rgb];
	        	$rgb  = getRGB($gd_resource, $i, ++$j);
	        }
	        --$j;

	        // 上色
    		foreach ($mark as $pos) {

    			if ($count <=2 ) {
	    			$color = $white;
    			} else {
    				$rgb = $pos[2];
					$color = imagecolorallocate($canvas, $rgb['r'], $rgb['g'], $rgb['b']);
    			}
            	imagesetpixel($canvas, $pos[0], $pos[1], $color);
    		}

		}
	}


	// 横向过滤点
    for ($j=0; $j<$h; $j++) {

		for ($i=0; $i<$w; $i++) {

	    	$rgb = getRGB($canvas, $i, $j);

	    	// 白色直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($canvas, $i, $j, $white);
	            continue;
	        }


	        // 记录数值 >=2 的值
	        $count = 0;
	        $mark  = [];
	        while (isBlack($rgb) && ++$count && $i < $w) {
	        	$mark[] = [$i, $j, $rgb];
	        	$rgb  = getRGB($canvas, ++$i, $j);
	        }
	        --$i;

	        // 上色
    		foreach ($mark as $pos) {
    			if ($count <=2 ) {
	    			$color = $white;
    			} else {
    				$rgb = $pos[2];
					$color = imagecolorallocate($canvas, $rgb['r'], $rgb['g'], $rgb['b']);
    			}
            	imagesetpixel($canvas, $pos[0], $pos[1], $color);
    		}
	    }
	}

	return $canvas;
}